package net.simflow.swf.analyzer.fileprinter;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.TreeSet;

import net.simflow.swf.analyzer.network.data.Flow;
import net.simflow.swf.analyzer.network.data.Link;
import net.simflow.swf.analyzer.network.data.Node;
import net.simflow.swf.analyzer.network.data.Service;
import net.simflow.swf.analyzer.network.stats.data.NetworkStats;

public class NetworkStatsFilePrinter {
	private static final LinkedHashMap<String, Boolean> DEFAULT_CONFIG = new LinkedHashMap<String, Boolean>();
	static {
		DEFAULT_CONFIG.put(NetworkStats.NAME, true);
		DEFAULT_CONFIG.put(NetworkStats.FLOW, true);
		DEFAULT_CONFIG.put(NetworkStats.NODE, true);
		DEFAULT_CONFIG.put(NetworkStats.SERVICE, true);
		DEFAULT_CONFIG.put(NetworkStats.LINK, true);
		DEFAULT_CONFIG.put(NetworkStats.DEGREE_DISTRIBUTION, true);
	}

	private static NetworkStatsFilePrinter instance = new NetworkStatsFilePrinter();

	private NetworkStatsFilePrinter() {
	}

	public static NetworkStatsFilePrinter getInstance() {
		return instance;
	}

	public void print(FilePrinter p, NetworkStats nstats) {
		if (p == null) {
			return;
		}
		if (nstats == null) {
			return;
		}

		p.print(FilePrinter.NEW_LINE + "Network Info:");
		for (Entry<String, Boolean> en : DEFAULT_CONFIG.entrySet()) {
			if (!en.getValue()) {
				continue;
			}
			String title = en.getKey();
			switch (title) {
			case NetworkStats.NAME:
				this.printNameString(p, title, nstats);
				break;
			case NetworkStats.FLOW:
				this.printFlowSetString(p, title, nstats);
				break;
			case NetworkStats.NODE:
				this.printNodeSetString(p, title, nstats);
				break;
			case NetworkStats.SERVICE:
				this.printServiceSetString(p, title, nstats);
				break;
			case NetworkStats.LINK:
				this.printLinkSetString(p, title, nstats);
				break;
			case NetworkStats.DEGREE_DISTRIBUTION:
				this.printDegreeDistributionString(p, title, nstats);
				break;
			}
		}
	}

	public void printNameString(FilePrinter p, String title, NetworkStats nstats) {
		if (nstats.getNetworkName() == null) {
			return;
		}
		p.print(FilePrinter.NEW_LINE + title + ":" + FilePrinter.TAB
				+ nstats.getNetworkName());
	}

	private void printFlowSetString(FilePrinter p, String title,
			NetworkStats nstats) {
		if (nstats.getFlowSet() == null) {
			return;
		}

		boolean is = true;

		TreeSet<String> set = new TreeSet<String>();
		for (Flow flow : nstats.getFlowSet()) {
			set.add(flow.getNameInNetwork() + ":" + flow.getFullInfo());
		}
		set.comparator();

		for (String str : set) {
			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ": "
						+ nstats.getFlowCount());
				is = false;
			}
			p.print(FilePrinter.TAB + str);
		}
	}

	private void printNodeSetString(FilePrinter p, String title,
			NetworkStats nstats) {
		if (nstats.getNodeSet() == null) {
			return;
		}

		boolean is = true;

		TreeSet<String> set = new TreeSet<String>();
		for (Node node : nstats.getNodeSet()) {
			set.add(node.getNameInNetwork() + ":" + node.getFullInfo());
		}
		set.comparator();

		for (String str : set) {
			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ": "
						+ nstats.getNodeCount());
				is = false;
			}
			p.print(FilePrinter.TAB + str);
		}
	}

	private void printServiceSetString(FilePrinter p, String title,
			NetworkStats nstats) {
		if (nstats.getServiceSet() == null) {
			return;
		}

		boolean is = true;

		TreeSet<String> set = new TreeSet<String>();
		for (Service service : nstats.getServiceSet()) {
			set.add(service.getNameInNetwork() + ":" + service.getFullInfo());
		}
		set.comparator();

		for (String str : set) {
			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ": "
						+ nstats.getServiceCount());
				is = false;
			}
			p.print(FilePrinter.TAB + str);
		}
	}

	private void printLinkSetString(FilePrinter p, String title,
			NetworkStats nstats) {
		if (nstats.getLinkSet() == null) {
			return;
		}

		boolean is = true;

		TreeSet<String> set = new TreeSet<String>();
		for (Link link : nstats.getLinkSet()) {
			set.add(link.getShortInfo());
		}
		set.comparator();

		for (String str : set) {
			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ": "
						+ nstats.getLinkCount());
				is = false;
			}
			p.print(FilePrinter.TAB + str);
		}
	}

	public void printDegreeDistributionString(FilePrinter p, String title,
			NetworkStats nstats) {
		if (nstats.getDegreeDistribution() == null) {
			return;
		}
		nstats.getDegreeDistribution().comparator();

		boolean is = true;
		for (Entry<Integer, ArrayList<Node>> en : nstats
				.getDegreeDistribution().descendingMap().entrySet()) {
			TreeSet<String> set = new TreeSet<String>();
			for (Node node : en.getValue()) {
				set.add(node.getNameInNetwork());
			}
			set.comparator();

			if (is) {
				p.print(FilePrinter.NEW_LINE + title + ":");
				is = false;
			}
			p.print(FilePrinter.TAB + en.getKey() + " (" + en.getValue().size()
					+ "): ");
			for (String s : set) {
				p.print(" " + s + ";");
			}
		}
	}
}
